<?php
/**
 * Base Model class
 * All Models must extend from this
 */
namespace PUF;

class Model {
	public static $useTable = null;
	
	protected static $database = null;
	
	protected $databaseFields = [];
	
	protected static function getDatabase() {
		if (self::$database == null) {
			self::$database = Database::getInstance();
		}
		
		return self::$database;
	}
	
	/**
	 * Executes a custom query
	 * @param string $sql : Sentence to execute
	 */
	public static function query($sql) {
		return self::getDatabase()->query($sql, get_called_class());
	}
	
	public function __construct($properties = []) {
		foreach ($properties as $property => $value) {
			$this->{$property} = $value;
		}
		
		$this->describeFields();
	}
	
	protected function describeFields() {
		if (static::$useTable) {
			$fields = $this->query('DESCRIBE ' . static::$useTable);
			
			$fields->setModel(null);
			while ($fields->hasNext()) {
				$this->databaseFields[] = $fields->next()['Field'];
			}
		}
	}
	
	public static function findBy($field, $value, $options = []) {
		if (!isset($options['conditions'])) {
			$options['conditions'] = [];
		}
		
		$options['conditions'][] = "$field = '$value'";
		$options['limit'] = 1;
		
		$result = self::find($options);
		
		if ($result->hasNext()) {
			return $result->next();
		}
		
		return null;
	}
	
	public static function find($options = []) {
		$sql = ' SELECT ';
		
		if (isset($options['fields'])) {
			foreach ($options['fields'] as $field) {
				$sql .= " $field , ";
			}
			$sql = substr($sql, 0, -2);
		} else {
			$sql .= ' * ';
		}
		
		$sql .= ' FROM ';
		
		$sql .= ' ' . static::$useTable . ' ';
		
		if (isset($options['conditions'])) {
			arrayizeObject($options['conditions']);
			$sql .= ' WHERE ';
			foreach ($options['conditions'] as $condition) {
				$sql .= " $condition AND ";
			}
			$sql = substr($sql, 0, -4);
		}
		
		if (isset($options['order'])) {
			$sql .= " ORDER BY {$options['order']} ";
		}
		
		if (isset($options['limit'])) {
			$sql .= ' LIMIT ';
			
			if (isset($options['offset'])) {
				$sql .= " {$options['offset']}, ";
			}
			
			$sql .= " {$options['limit']} ";
		}

		return self::query($sql);
	}
	
	public static function count($options = []) {
		$sql = ' SELECT count( ';
		
		if (isset($options['fields'])) {
			foreach ($options['fields'] as $field) {
				$sql .= " $field , ";
			}
			$sql = substr($sql, 0, -2);
		} else {
			$sql .= ' * ';
		}
		
		$sql .= ' ) as quantity ';
		
		$sql .= ' FROM ';
		
		$sql .= ' ' . static::$useTable . ' ';
		
		if (isset($options['conditions'])) {
			arrayizeObject($options['conditions']);
			$sql .= ' WHERE ';
			foreach ($options['conditions'] as $condition) {
				$sql .= " $condition AND ";
			}
			$sql = substr($sql, 0, -4);
		}
		
		if (isset($options['order'])) {
			$sql .= " ORDER BY {$options['order']} ";
		}
		
		if (isset($options['limit'])) {
			$sql .= ' LIMIT ';
			
			if (isset($options['offset'])) {
				$sql .= " {$options['offset']}, ";
			}
			
			$sql .= " {$options['limit']} ";
		}

		return self::query($sql)->next()->quantity;
	}
	
	public function setFromRequest() {
		foreach ($_REQUEST as $property => $value) {
			$this->{$property} = $value;
		}
	}
	
	public function save() {
		$sql = '';
		
		if (isset($this->id) && $this->id) {
			$sql .= ' UPDATE ' . static::$useTable . ' SET ';
			
			foreach ($this->databaseFields as $field) {
				if (isset($this->{$field}) && $this->{$field}) {
					$sql .= " `{$field}` = '" . $this->{$field} . "', ";
				} else {
					$sql .= " `{$field}` = null, ";
				}
			}
			$sql = substr($sql, 0, -2);
			
			$sql .= " WHERE `id` = {$this->id} ";
			
		} else {
			$sql .= ' INSERT INTO ' . static::$useTable . ' ( ';
			
			foreach ($this->databaseFields as $field) {
				$sql .= " `{$field}`, ";
			}
			$sql = substr($sql, 0, -2);
			$sql .= ' ) VALUES ( ';
			
			foreach ($this->databaseFields as $field) {
				if (isset($this->{$field}) && $this->{$field}) {
					$sql .= " '" . $this->{$field} . "', ";
				} else {
					$sql .= ' null, ';
				}
			}
			$sql = substr($sql, 0, -2);
			$sql .= ' ) ';
		}
		
		self::query($sql);
	}
}